package org.redr.canvas;

import java.util.HashMap;
import java.util.Map;

import java.util.ArrayList;
import java.util.List;

import org.redr.widgetGUI.core.RedRWidgetGUI;
import org.redr.widgetGUI.settings.RVariableSettings;
import org.redr.widgetGUI.settings.WidgetSettings;
import org.rosuda.REngine.REXP;

import com.trolltech.qt.core.QRectF;

/*
 * RRW (RedR Widget) is the base class of all RedR Widgets.  
 * Widgets should implement this class as their base class (extends RRW).  
 * 
 * Methods include closeWidget, deleteWidget, openWidget, send, 
 */


public abstract class RRW{
	
	// private RedRSignalManager signalManager = RedRSignalManager;
	public static String widgetType = "Core RRW";
	protected String widgetId = "test";
	protected RedRWidgetGUI gui;			// gui is the underlying RedRWidgetGUI for this widget.
	protected WidgetSettings settings;	// settings is the widget settings that this widget uses to retain information
	private Map<String, InputSocket> inputs = new HashMap<String, InputSocket>();
	private Map<String, OutputSocket> outputs = new HashMap<String, OutputSocket>();
	protected RVariableSettings rvarSettings;
	
	
	public RRW(RedRWidgetGUI w, WidgetSettings ws){
		gui = w;
		settings = ws;
		initSettings();
		_initVariables();
		initSignals();
		initGUI();
	}
	
	public RRW(WidgetSettings ws){
		gui = new RedRWidgetGUI(ws);
		settings = ws;
		initSettings();
		_initVariables();
		initSignals();
		initGUI();
	}
	
	private void initSettings(){
		this.widgetId = settings.getSetting("widgetId");
	}
	
	public String caption(){
		return settings.getSetting("caption");
	}
	
	public void setCaption(String s){
		gui.mainWindow.setWindowTitle(s);
		settings.setSetting("caption", s);
	}
	
	/**
	 * Abstract method that initiates the inputs and outputs of the widget.
	 */
	protected abstract void initSignals();

	/**
	 * Abstract method that initiates the gui for this widget.
	 * Should make use of the gui and settings attributes of this class.
	 */
	protected abstract void initGUI(); 
	
	/**
	 * This function should be filled with calls to set data in the rvarSettings.
	 * The function should contain several of these;
	 * <strong>rvarSettings.setDefault("varname", makeVarName("varname"));</strong>
	 * Be sure to use the setDefault option as this will not override any variable names
	 * that are already set by the widget.
	 * 
	 * You can also use this section to get and set variables that you plan to use in the 
	 * session in the same way;</br>
	 * <strong>rvarSettings.setDefault("myVar", "1");</br>
	 * this.someVar = rvarSettings.getSetting("myVar");</strong></br>
	 * Be sure to set myVar each time you want to change some variable
	 * in the widget so that it will be restored when the widget is reloaded.
	 */
	protected abstract void initVariables();
	
	
	/**
	 * Abstract method that will be called when a connection is made.  This should be overridden 
	 * in child classes to handle signal connection information.
	 * @param id
	 * @param data
	 * @param widgetId
	 */
	protected abstract void dataInput(String id, Object data, String widgetId);
	
	
	/*
	/**
	 * This function performs two steps at once.  First it sets the 
	 * signal parameter to be the data in the id parameter OutputSocket.
	 * Next the core RedRSignalManager.sendData function is called so that 
	 * all currently attached widgets will receive the new data.
	 * 
	 * @param id
	 * @param signal
	 */
	protected void send(String sid)
	{
		RedRSignalManager.sendData(widgetId, sid);
	}

	
	protected void addInput(InputSocket ins)
	{
		inputs.put(ins.getSignalId(), ins);
		RedRSignalManager.addInput(ins);
	}
	
	protected void addOutput(OutputSocket outs){
		outputs.put(outs.getSignalId(), outs);
		RedRSignalManager.addOutput(outs);
	}
	
	
	private void _initVariables(){
		rvarSettings = settings.getRVariableSettings();
		// TODO fill in this section
		initVariables();
		
	}
	
	
	
	
	/*
	 * Functions for opening, closing, and deleting widgets.  These are called by the canvas.
	 */
	
	public void closeWidget()
	{
		RedRLog.log(RedRLog.core, RedRLog.debug, "closing widget");
		gui.mainWindow.close();
	}
	
	public void openWidget()
	{
		RedRLog.log(RedRLog.core, RedRLog.debug, "open widget");
		gui.mainWindow.show();
	}
	
	public void deleteWidget()
	{
		RedRLog.log(RedRLog.core, RedRLog.debug, "delete widget");
	}
	
	/*
	 * R functions
	 */
	protected REXP R(String s) throws Exception
	{
		return RSession.R(s);
	}
	
	protected void nullR(String s) throws Exception{
		RSession.RVoideval(s);
	}
	
	protected String captureR(String s) throws Exception{
		REXP rs = this.R(String.format("paste(capture.output(%s), collapse = \"\\n\")", s));
		return rs.asString();
	}
	
	protected String _(String s){
		return s;
	}

	public String widgetID() {
		// TODO Auto-generated method stub
		return widgetId;
	}
	
	public RedRWidgetGUI gui(){
		return gui;
	}

	public boolean signalLocked() {
		// TODO Auto-generated method stub
		return false;
	}

	public Map<String, OutputSocket> outputs() {
		// TODO Auto-generated method stub
		return outputs;
	}

	public Map<String, InputSocket> inputs() {
		// TODO Auto-generated method stub
		return inputs;
	}

	public SignalClass getSignalDataBySocket(String id) {
		// TODO Auto-generated method stub
		OutputSocket socket = outputs.get(id);
		// this is really an error and should be changed in final version TODO
		if (socket == null) return null;
		return socket.currentSignal();
	}
	
	public String makeVarName(String basename){
		return String.format("%s_%s", basename, widgetID());
	}
	
	public OutputSocket outputsGet(String id){
		return this.outputs().get(id);
	}
	
	public InputSocket inputsGet(String id){
		return this.inputs().get(id);
	}
	
	protected void setStatus(int status, String message){
		// TODO
	}

}
